package main

import "fmt"

// 抽象原型接口
type EnemyPrototype interface {
	Clone() EnemyPrototype
	Attack() string // 示例方法
}

// ---------------------- 具体原型：海盗敌人 ----------------------
type PirateEnemy struct {
	Name      string
	Skills    []string      // 复杂对象（需要深拷贝）
	Waypoints []*Coordinate // 指针类型数据
	weapon    *Weapon       // 私有字段
}

// 实现深拷贝逻辑（核心）
func (p *PirateEnemy) Clone() EnemyPrototype {
	// 复制基础字段
	copyPirate := &PirateEnemy{
		Name:   p.Name + "_Clone",
		weapon: p.weapon.Copy(), // 深拷贝武器对象
	}

	// 深拷贝切片（重要！）
	copyPirate.Skills = make([]string, len(p.Skills))
	copy(copyPirate.Skills, p.Skills)

	// 深拷贝指针结构体切片
	copyPirate.Waypoints = make([]*Coordinate, len(p.Waypoints))
	for i, wp := range p.Waypoints {
		copyWp := *wp // 解引用后复制结构体内容
		copyPirate.Waypoints[i] = &copyWp
	}

	return copyPirate
}

func (p *PirateEnemy) Attack() string {
	return fmt.Sprintf("%s 使用 %s 发动攻击！", p.Name, p.weapon.Name)
}

// ---------------------- 坐标结构体 ----------------------
type Coordinate struct {
	X, Y float64
}

// ---------------------- 武器类（需实现深拷贝） ----------------------
type Weapon struct {
	Name  string
	Power int
}

func (w *Weapon) Copy() *Weapon {
	return &Weapon{
		Name:  w.Name,
		Power: w.Power,
	}
}

// ---------------------- 原型管理器 ----------------------
type EnemyRegistry struct {
	prototypes map[string]EnemyPrototype
}

func NewEnemyRegistry() *EnemyRegistry {
	return &EnemyRegistry{
		prototypes: make(map[string]EnemyPrototype),
	}
}

// 预加载原型对象（模拟耗时操作）
func (r *EnemyRegistry) LoadPrototypes() {
	// 初始化复杂海盗原型
	pirate := &PirateEnemy{
		Name:      "精英海盗",
		Skills:    []string{"火枪射击", "近战劈砍"},
		Waypoints: []*Coordinate{{X: 100, Y: 200}, {X: 150, Y: 180}},
		weapon:    &Weapon{Name: "弯刀", Power: 50},
	}
	r.prototypes["pirate"] = pirate

	// 可添加其他类型敌人...
}

// 获取克隆体
func (r *EnemyRegistry) SpawnEnemy(typeName string) EnemyPrototype {
	proto, ok := r.prototypes[typeName]
	if !ok {
		panic("未知敌人类型")
	}
	return proto.Clone()
}

// ---------------------- 客户端调用 ----------------------
func main() {
	// 初始化原型管理器（通常游戏启动时执行一次）
	registry := NewEnemyRegistry()
	registry.LoadPrototypes() // 模拟加载资源

	// 生成10个海盗敌人（通过克隆而非重新初始化）
	for i := 0; i < 10; i++ {
		enemy := registry.SpawnEnemy("pirate").(*PirateEnemy)
		fmt.Println(enemy.Attack())
		fmt.Printf("路径点地址是否相同: %v\n",
			enemy.Waypoints[0] == registry.prototypes["pirate"].(*PirateEnemy).Waypoints[0])
	}
}
